
enum Message {
    Quit,
    Move{x:i32,y:i32},
    Write(String),
    ChangeColor(i32,i32,i32),
}

fn main() {
    let w = 30;
    let l = 50;

    // let rect = (30,50);

    // println!("{}", area(w,l));
    // println!("{}", area(rect));

    let rect = Rectangle {
        width: 30,
        length: 50,
    };
    let rect1 = Rectangle {
        width: 10,
        length: 50,
    };let rect2 = Rectangle {
        width: 20,
        length: 70,
    };


    println!("{}", area(&rect));

    println!("{:?}",rect);

    println!("{}", rect.can_hold(&rect1));
    println!("{}", rect.can_hold(&rect2));

    println!("{:?}", Rectangle::square(20));

    let four = IpAddress::V4;
    let six = IpAddress::V6;

    route(four);
    route(six);
    route(IpAddress::V6);

    let home = IpAddr {
        kind: IpAddress::V4,
        address: String::from("127.0.0.1"),
    };

    let loopback = IpAddr {
        kind: IpAddress::V6,
        address: String::from("::1"),
    };

    let home1 = IpAddress1::V4(127,0,0,1);
    let home2 = IpAddress1::V6(String::from("::1"));


    let q = Message::Quit;
    let m = Message::Move {x: 12,y: 24};
    let w = Message::Write(String::from("Hello"));
    let c = Message::ChangeColor(0,255,255);

    m.call();

    let some_number = Some(5);
    let some_string = Some("A String");
    let absent_number: Option<i32> = None;
}

impl Message {
    fn call(&self) {

    }
}

// 与struct对比，使用枚举的优势 1、不需要额外使用struct 2、每个变体可以拥有不同的类型以及关联的数据量
enum IpAddress {
    V4,
    V6,
}

enum IpAddress1 {
    V4(u8,u8,u8,u8),
    V6(String),
}

struct IpAddr {
    kind: IpAddress,
    address: String,
}

// 手动实现debug，打印出实例，为debug注解
// std::fmt::Display、std::fmt::Debug、{:#?}
#[derive(Debug)]
struct Rectangle {
    width: u32,
    length: u32,
}

// fn area(dim: (u32, u32)) -> u32 {
//     dim.0 * dim.1
// }

fn area(rect: &Rectangle) -> u32 {
    rect.width * rect.length
}

impl Rectangle {
    fn area (&self) -> u32 {
        self.width * self.length
    }

    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.length && self.length > other.length
    }

    fn square(size: u32) -> Rectangle {
        Rectangle {
            width: size,
            length: size,
        }
    }
}

